﻿using Microsoft.Extensions.Caching.Memory;

namespace HZY.Framework.Core.Filters;

/// <summary>
/// Interface resource load filtering blocks resources for caching
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class ApiResourceCacheFilterAttribute : Attribute, IResourceFilter
{
    private readonly double _cacheTime;

    public ApiResourceCacheFilterAttribute(double cacheTime)
    {
        _cacheTime = cacheTime;
    }

    /// <summary>
    /// Before resource loading
    /// </summary>
    /// <param name="context"></param>
    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        var memoryCache = context.HttpContext.RequestServices.GetService(typeof(IMemoryCache)) as IMemoryCache;

        if (memoryCache == null)
        {
            return;
        }

        var apiResourceCacheKey = GetCacheKey(context.HttpContext);
        var result = memoryCache.Get(apiResourceCacheKey);
        if (result != null)
        {
            context.Result = result as IActionResult;
        }
    }

    /// <summary>
    /// After resource loading
    /// </summary>
    /// <param name="context"></param>
    public void OnResourceExecuted(ResourceExecutedContext context)
    {
        var memoryCache = context.HttpContext.RequestServices.GetService(typeof(IMemoryCache)) as IMemoryCache;

        if (memoryCache == null)
        {
            return;
        }

        var apiResourceCacheKey = GetCacheKey(context.HttpContext);
        var result = memoryCache.Get(apiResourceCacheKey);

        if (result == null && context.Result != null)
        {
            memoryCache.Set(apiResourceCacheKey, context.Result, DateTime.Now.AddSeconds(_cacheTime));
        }
    }

    /// <summary>
    /// Gets the cache key for each unique request
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private static string GetCacheKey(HttpContext context)
    {
        var requestId = context.TraceIdentifier.Split(':')[0];
        return $"{requestId}=>{context.Request.Path.ToString()?.ToLower()}";
    }
}